Passed
Push — master ( 118f1b...bbe4cb )
by Dev
01:51
created

helpers.js ➔ formToSky   F

Complexity

Conditions 17

Size

Total Lines 76
Code Lines 48

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 17
eloc 48
dl 0
loc 76
rs 1.8
c 0
b 0
f 0

1 Function

Rating   Name   Duplication   Size   Complexity  
A helpers.js ➔ responsiveImage 0 17 5

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like helpers.js ➔ formToSky often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
/**
2
 * List of all functions
3
 *
4
 * - liveBlock(attr)
5
 * - liveForm(attr)
6
 *
7
 * - responsiveImage(string)    Relative to Liip filters
8
 * - uncloakLinks(attr)
9
 * - convertFormFromRot13(attr)
10
 * - readableEmail(attr)
11
 * - convertImageLinkToWebPLink()
12
 */
13
14
/**
15
 * Fetch (ajax) function permitting to get block via a POST request
16
 * (prevent from spam)
17
 *
18
 * @param {string} attribute
19
 */
20
export function liveBlock(attribute = "data-live") {
21
  document.querySelectorAll("[" + attribute + "]").forEach(item => {
22
    fetch(item.getAttribute(attribute), {
23
      headers: { "Content-Type": "application/json", Accept: "text/plain" },
24
      method: "POST",
25
      credentials: "same-origin"
26
    })
27
      .then(function(response) {
28
        return response.text();
29
      })
30
      .then(function(body) {
31
        item.removeAttribute(attribute);
32
        item.innerHTML = body;
33
34
        document.dispatchEvent(new Event("DOMChanged"));
0 ignored issues
show
Bug introduced by
The variable Event seems to be never declared. If this is a global, consider adding a /** global: Event */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
35
      });
36
  });
37
}
38
39
/**
40
 * ajaxify-form
41
 */
42
export function liveForm(selector = '.live-form') {
43
  document.querySelectorAll(selector).forEach(item => {
44
    if (item.querySelector("form") !== null) {
45
      item.querySelector("form").addEventListener("submit", e => {
46
        e.preventDefault();
47
        sendForm(e);
48
      });
49
    }
50
  });
51
52
  var setLoader = function (form) {
53
    var $submitButton = getSubmitButton(form);
54
    if ($submitButton !== null) {
55
      var initialButton = $submitButton.outerHTML;
0 ignored issues
show
Unused Code introduced by
The variable initialButton seems to be never used. Consider removing it.
Loading history...
56
      $submitButton.innerHTML = '';
57
      $submitButton.outerHTML = '<div style="width:1em;height:1em;border: 3px solid #222;border-top-color: #fff;border-radius: 50%;  animation: 1s spin linear infinite;"></div><style>@keyframes spin {from{transform:rotate(0deg)}to{transform:rotate(360deg)}}</style>';
58
    }
59
  }
60
  
61
  var sendForm = function(form) {
62
     setLoader(form);
63
     
64
    var formData = new FormData(form.srcElement);
65
    fetch(form.srcElement.action, {
66
      method: "POST",
67
      body: formData,
68
      credentials: "same-origin"
69
    })
70
      .then(function(response) {
71
        return response.text();
72
      })
73
      .then(function(body) {
74
        form.srcElement.outerHTML = body;
75
76
        document.dispatchEvent(new Event("DOMChanged"));
0 ignored issues
show
Bug introduced by
The variable Event seems to be never declared. If this is a global, consider adding a /** global: Event */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
77
      })
78
      .then(function() {
79
        document.dispatchEvent(new Event("DOMChanged"));
0 ignored issues
show
Bug introduced by
The variable Event seems to be never declared. If this is a global, consider adding a /** global: Event */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
80
      });
81
  };
82
83
  var getSubmitButton = function(form) {
84
    if (form.srcElement.querySelector("[type=submit]") !== null) {
85
      return form.srcElement.querySelector("[type=submit]");
86
    }
87
    if (form.srcElement.getElementsByTagName("button") !== null) {
88
      return form.srcElement.getElementsByTagName("button")[0];
89
    }
90
    return null;
91
  };
92
}
93
94
/**
95
 * Transform image's path (src) produce with Liip to responsive path
96
 *
97
 * @param {string} src
98
 */
99
export function responsiveImage(src) {
100
  var screenWidth = window.innerWidth;
101
  if (screenWidth <= 576) {
102
    src = src.replace("/default/", "/xs/");
103
  } else if (screenWidth <= 768) {
104
    src = src.replace("/default/", "/sm/");
105
  } else if (screenWidth <= 992) {
106
    src = src.replace("/default/", "/md/");
107
  } else if (screenWidth <= 1200) {
108
    src = src.replace("/default/", "/lg/");
109
  } else {
110
    // 1200+
111
    src = src.replace("/default/", "/xl/");
112
  }
113
114
  return src;
115
}
116
117
/**
118
 * Convert elements wich contain attribute (data-href) in normal link (a href)
119
 * You can use a callback function to decrypt the link (eg: rot13ToText ;-))
120
 *
121
 * @param {string}  attribute
122
 */
123
export async function uncloakLinks(attribute = "data-rot") {
124
  var convertLink = function(element) {
125
    // fix "bug" with img
126
    if (element.getAttribute(attribute) === null) {
127
      var element = element.closest("[" + attribute + "]");
128
    }
129
    if (element.getAttribute(attribute) === null) return;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
Comprehensibility Best Practice introduced by
Are you sure this return statement is not missing an argument? If this is intended, consider adding an explicit undefined like return undefined;.
Loading history...
130
    var link = document.createElement("a");
131
    var href = element.getAttribute(attribute);
132
    element.removeAttribute(attribute);
133
    for (var i = 0, n = element.attributes.length; i < n; i++) {
134
      link.setAttribute(
135
        element.attributes[i].nodeName,
136
        element.attributes[i].nodeValue
137
      );
138
    }
139
    link.innerHTML = element.innerHTML;
140
    link.setAttribute(
141
      "href",
142
      responsiveImage(convertShortchutForLink(rot13ToText(href)))
143
    );
144
    element.parentNode.replaceChild(link, element);
145
    return link;
146
  };
147
148
  var convertThemAll = function(attribute) {
149
    [].forEach.call(document.querySelectorAll("[" + attribute + "]"), function(
150
      element
151
    ) {
152
      convertLink(element);
153
    });
154
  };
155
156
  var fireEventLinksBuilt = async function(element, event) {
157
    await document.dispatchEvent(new Event("linksBuilt"));
0 ignored issues
show
Bug introduced by
The variable Event seems to be never declared. If this is a global, consider adding a /** global: Event */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
158
159
    var clickEvent = new Event(event.type);
160
    element.dispatchEvent(clickEvent);
161
  };
162
163
  var convertLinkOnEvent = async function(event) {
164
    // convert them all if it's an image (thanks this bug), permit to use gallery (baguetteBox)
165
    if (event.target.tagName == "IMG") {
166
      await convertThemAll(attribute);
167
      var element = event.target;
168
    } else {
169
      var element = convertLink(event.target);
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable element already seems to be declared on line 167. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
170
    }
171
    fireEventLinksBuilt(element, event);
172
  };
173
174
  [].forEach.call(document.querySelectorAll("[" + attribute + "]"), function(
175
    element
176
  ) {
177
    element.addEventListener(
178
      "touchstart",
179
      function(e) {
180
        convertLinkOnEvent(e);
181
      },
182
      { once: true }
183
    );
184
    element.addEventListener(
185
      "click",
186
      function(e) {
187
        convertLinkOnEvent(e);
188
      },
189
      { once: true }
190
    );
191
    element.addEventListener(
192
      "mouseover",
193
      function(e) {
194
        convertLinkOnEvent(e);
195
      },
196
      { once: true }
197
    );
198
  });
199
}
200
201
/**
202
 * Convert action attr encoded in rot 13 to normal action with default attr `data-frot`
203
 *
204
 * @param {string}  attribute
205
 */
206
export function convertFormFromRot13(attribute = "data-frot") {
207
  [].forEach.call(document.querySelectorAll("[" + attribute + "]"), function(
208
    element
209
  ) {
210
    var action = element.getAttribute(attribute);
211
    element.removeAttribute(attribute);
212
    element.setAttribute(
213
      "action",
214
      convertShortchutForLink(rot13ToText(action))
215
    );
216
  });
217
}
218
219
export function convertShortchutForLink(str) {
220
  if (str.charAt(0) == "-") {
221
    return str.replace("-", "http://");
222
  }
223
  if (str.charAt(0) == "_") {
224
    return str.replace("_", "https://");
225
  }
226
  if (str.charAt(0) == "@") {
227
    return str.replace("@", "mailto:");
228
  }
229
  return str;
230
}
231
232
/**
233
 * readableEmail(selector) Transform an email encoded with rot13 in a readable mail (and add mailto:)
234
 *
235
 * @param {string}  text
236
 */
237
export function readableEmail(selector) {
238
  document.querySelectorAll(selector).forEach(function(item) {
239
    var mail = rot13ToText(item.textContent);
240
    item.innerHTML = '<a href="mailto:' + mail + '">' + mail + "</a>";
241
    if (selector.charAt(0) == ".") {
242
      item.classList.remove(selector.substring(1));
243
    }
244
  });
245
}
246
247
/**
248
 * Decode rot13
249
 *
250
 * @param {string}  str
251
 */
252
export function rot13ToText(str) {
253
  return str.replace(/[a-zA-Z]/g, function(c) {
254
    return String.fromCharCode(
255
      (c <= "Z" ? 90 : 122) >= (c = c.charCodeAt(0) + 13) ? c : c - 26
256
    );
257
  });
258
}
259
260
export function testWebPSupport() {
261
  var elem = document.createElement("canvas");
262
263
  if (elem.getContext && elem.getContext("2d")) {
264
    return elem.toDataURL("image/webp").indexOf("data:image/webp") == 0;
0 ignored issues
show
Best Practice introduced by
Comparing elem.toDataURL("image/we...exOf("data:image/webp") to 0 using the == operator is not safe. Consider using === instead.
Loading history...
265
  }
266
267
  return false;
268
}
269
270
/**
271
 * Used in ThemeComponent
272
 */
273
export function convertImageLinkToWebPLink() {
274
  var switchToWebP = function() {
275
    [].forEach.call(document.querySelectorAll("a[dwl]"), function(element) {
276
      var href = responsiveImage(element.getAttribute("dwl"));
277
      element.setAttribute("href", href);
278
      element.removeAttribute("dwl");
279
    });
280
  };
281
282
  if (testWebPSupport()) switchToWebP();
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
283
}
284
285
/**
286
 * Simple Image Lazy Loader
287
 * original from : https://davidwalsh.name/lazyload-image-fade
288
 *
289
 * @param {string}  attribute
290
 *
291
 * @example
292
 * imgLazyLoad()
293
 * <span data-img=/img/me.png>Tagada</span> or <img data-img=/img/me.png alt=Tagada>
294
 *
295
 * will be converted to
296
 *
297
 * <img src=/img/me.png alt=Tagada />
298
 * 
299
 * still used in piedvert. To remove ?!
300
 */
301
export function imgLazyLoad(attribute = "data-img") {
302
  [].forEach.call(document.querySelectorAll("[" + attribute + "]"), function(
303
    img
304
  ) {
305
    var newDomImg = document.createElement("img");
306
    var src = img.getAttribute(attribute);
307
    img.removeAttribute(attribute);
308
    for (var i = 0, n = img.attributes.length; i < n; i++) {
309
      newDomImg.setAttribute(
310
        img.attributes[i].nodeName,
311
        img.attributes[i].nodeValue
312
      );
313
    }
314
    if (newDomImg.getAttribute("alt") === null && img.textContent != "") {
315
      newDomImg.setAttribute("alt", img.textContent);
316
    }
317
    newDomImg.setAttribute(
318
      "src",
319
      typeof responsiveImage === "function" ? responsiveImage(src) : src
320
    );
321
    img.outerHTML = newDomImg.outerHTML;
322
  });
323
}
324